package in.muton.edushare.pages.folder;

import in.muton.edushare.EduShareSession;
import in.muton.edushare.auth.roles.CourseRoleCheck;
import in.muton.edushare.auth.roles.DeptRoleCheck;
import in.muton.edushare.auth.roles.UnivRoleCheck;
import in.muton.edushare.auth.roles.UserUserRelationshipCheck;
import in.muton.edushare.url.EntityPageParams;
import in.muton.edushare.wicket.models.CayenneModel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.wicket.PageParameters;

import com.edushare.common.constants.RequestConstants;
import com.edushare.common.dao.CourseInstancesDAO;
import com.edushare.common.dao.DepartmentsDAO;
import com.edushare.common.dao.GroupsDAO;
import com.edushare.common.dao.UniversitiesDAO;
import com.edushare.common.dao.UsersDAO;
import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.Courses;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Enrolments;
import com.edushare.common.vo.FileDirectories;
import com.edushare.common.vo.FileFolderObject;
import com.edushare.common.vo.FilesUploaded;
import com.edushare.common.vo.Groups;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.UserDeptLink;
import com.edushare.common.vo.UserRoles;
import com.edushare.common.vo.Users;

public class FolderHelper {
	
	
	/** converts encrypted read-write codes into readable strings */
	public static String getFolderReadPermissionString(String readPerm, Integer ownerType) {
		if(ownerType != FileDirectories.DIRECTORY_OWNER_TYPE.USER.getIntVal())
			return getFolderReadPermissionString(readPerm);
		
		if(readPerm.equalsIgnoreCase(FileDirectories.PERM_PUBLIC)){
			return "Anyone on the web";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_UNIV_STUDENTS)){
			return "Everyone in my university";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_UNIV_TEACHER)){
			return "All faculty in my university";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_DEPT_STUDENT)){
			return "Everyone in my departments";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_DEPT_TEACHER)){
			return "My Departments' faculty only";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_COURSE_STUDENT)){
			return "Everyone in my courses";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_COURSE_TEACHER)){
			return "faculties of my courses";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_COURSE_ADMIN)){
			return "Admins of my courses only";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_DEPT_ADMIN)){
			return "Admins of my departments";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_UNIV_ADMIN)){
			return "Administrators of my university only";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_PRIVATE)){
			return "Only me";
		}else if(readPerm.equalsIgnoreCase(FileDirectories.PERM_GROUP_MEMBERS)){
			return "Group members only";
		}
		return null;
	}

	public static String getFolderReadPermissionString(String permission){
		
		String permissionCode = permission;
		
		if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_PUBLIC)){
			return "Anyone on the web";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_UNIV_STUDENTS)){
			return "Everyone in the university";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_UNIV_TEACHER)){
			return "All faculty in university";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_DEPT_STUDENT)){
			return "Everyone in the department";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_DEPT_TEACHER)){
			return "Department's faculty only";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_COURSE_STUDENT)){
			return "Everyone in the course";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_COURSE_TEACHER)){
			return "Course faculty only";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_COURSE_ADMIN)){
			return "Course administrators only";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_DEPT_ADMIN)){
			return "Department's administrators only";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_UNIV_ADMIN)){
			return "University administrators only";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_PRIVATE)){
			return "Only me";
		}else if(permissionCode.equalsIgnoreCase(FileDirectories.PERM_GROUP_MEMBERS)){
			return "Group members only";
		}
		return "";
	}

	/**
	 * 
	 * @param ownerType
	 * @param parentDir
	 * @return helper method that returns human readable permission string for a List of permission codes
	 */
	public static HashMap<String, String> getAvailablePermissionsMap(List<String> avlPerms, Integer ownerType) {

		HashMap<String, String> hm = new HashMap<String, String>();
		for(String perm:avlPerms){
			hm.put(perm, getFolderReadPermissionString(perm, ownerType));
		}
		return hm;
	}
	
	/**
	 * 
	 * @param FileList
	 * @param FolderList
	 * @return Merged list of fileList and folderList as List of FileFolderObject
	 */
	
	public static List<FileFolderObject> mergeLists(List<FilesUploaded> fuList, List<FileDirectories> fdList){
		ArrayList<FileFolderObject> ffol = new ArrayList<FileFolderObject>();
		appendFolders(ffol, fdList);
		appendFiles(ffol, fuList);
		return ffol;
	}

	private static void appendFiles(ArrayList<FileFolderObject> ffol, List<FilesUploaded> fuList) {
		if(ffol==null || fuList == null)
			return;
		for(FilesUploaded fu: fuList){
			ffol.add(new FileFolderObject(fu));
		}
	}

	private static void appendFolders(ArrayList<FileFolderObject> ffol, List<FileDirectories> fdList) {
		if(ffol==null || fdList == null)
			return;
		for(FileDirectories fd: fdList){
			ffol.add(new FileFolderObject(fd));
		}
	}
	
	public static PageParameters getDirectoryPageParameters(FileDirectories fd){
		PageParameters pp=null;
		ORMInterface ormInterface = EduShareSession.get().getSessionORMInterface();
		if(fd.getOwnerType()==FileDirectories.DIRECTORY_OWNER_TYPE.COURSE_INSTANCE.getIntVal()){
			CourseInstances ci = new CourseInstancesDAO(ormInterface).getCourseInstanceById(fd.getOwnerId());
			CayenneModel<Courses> c = new CayenneModel<Courses>(ci.getCourse());
			String[] paramArr = {ci.getCourseInstanceId().toString()};
			pp = EntityPageParams.getParams(c, paramArr);
			pp.add(RequestConstants.PARAM_FOLDER_ID, fd.getFileDirectoryId().toString());
			
		}else if(fd.getOwnerType()==FileDirectories.DIRECTORY_OWNER_TYPE.DEPARTMENT.getIntVal()){
			Departments d = new DepartmentsDAO(ormInterface).getDepartmentByPk(fd.getOwnerId());
			pp = EntityPageParams.getParams(new CayenneModel<Departments>(d));
			pp.add(RequestConstants.PARAM_FOLDER_ID, fd.getFileDirectoryId().toString());
			
		}else if(fd.getOwnerType()==FileDirectories.DIRECTORY_OWNER_TYPE.UNIVERSITY.getIntVal()){
			Universities u = new UniversitiesDAO(ormInterface).getUnivById(fd.getOwnerId());
			pp = EntityPageParams.getParams(new CayenneModel<Universities>(u));
			pp.add(RequestConstants.PARAM_FOLDER_ID, fd.getFileDirectoryId().toString());
			
		}else if(fd.getOwnerType()==FileDirectories.DIRECTORY_OWNER_TYPE.USER.getIntVal()){
			Users u = new UsersDAO(ormInterface).getUserByPk(fd.getOwnerId());
			pp = EntityPageParams.getParams(new CayenneModel<Users>(u));
			pp.add(RequestConstants.PARAM_FOLDER_ID, fd.getFileDirectoryId().toString());
			
		}else if(fd.getOwnerType()==FileDirectories.DIRECTORY_OWNER_TYPE.GROUP.getIntVal()){
			Groups g = new GroupsDAO(ormInterface).getGroupById(fd.getOwnerId());
			pp = EntityPageParams.getParams(new CayenneModel<Groups>(g));
			pp.add(RequestConstants.PARAM_FOLDER_ID, fd.getFileDirectoryId().toString());
			
		}
		return pp;
	}

	/**
	 * NOTE; THIS FUNCTION HEAVILY DEPENDS ON FildeDirectories.getAllPermissions....
	 * Any change there must be reflected here.. else system may behave unexpectedly
	 * 
	 * 1. get the dir context i.e. owner, 2. get perms decreasing scope as arranged in FildeDirectories.getAllPermissions
	 * 3. get users all possible links with 
	 * @param u
	 * @param dir
	 * @return
	 */
	public static List<String> getUserVisibilityUnderDir(Users u, FileDirectories dir){
		ORMInterface ormInterface = EduShareSession.get().getSessionORMInterface();
		ArrayList<String> allowedPerms = new ArrayList<String>();
		List<String> allPerms = FileDirectories.getAllPermissions(dir.getOwnerType());
		int exitOn = allPerms.size()-1;
		int exitIndex = 0;
		
		if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.COURSE_INSTANCE.getIntVal()){
			
			CourseInstances ci = new CourseInstancesDAO(ormInterface).getCourseInstanceById(dir.getOwnerId());
			CourseRoleCheck crc = new CourseRoleCheck(ci, u);
			if(crc.isAdmin() || crc.isTeacher()){
				exitIndex = exitOn;
			}
			else if(crc.isStudent()){
				if(exitIndex < exitOn-1)
					exitIndex = exitOn-1;
			}else if(CourseRoleCheck.isDeptMember(ci, u)){
				if(exitIndex < exitOn-2)
					exitIndex = exitOn-2;
			}else if(CourseRoleCheck.isUnivMember(ci, u)){
				if(exitIndex < exitOn-3)
					exitIndex = exitOn-3;
			}
			
			
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.DEPARTMENT.getIntVal()){
			Departments d = new DepartmentsDAO(ormInterface).getDepartmentByPk(dir.getOwnerId());
			DeptRoleCheck drc = new DeptRoleCheck(d, u);
			if(drc.isUnivAdmin()|| drc.isPrimaryAdmin()||drc.isSecondaryAdmin()){
				exitIndex = exitOn;
			}else if(drc.isTeacher()){
				if(exitIndex < exitOn-1)
					exitIndex = exitOn-1;
			}else if(drc.isStudent()){
				if(exitIndex < exitOn-2)
					exitIndex = exitOn-2;
			}else if (DeptRoleCheck.isUnivMember(d, u)){
				if(exitIndex < exitOn-3)
					exitIndex = exitOn-3;
			}
			
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.UNIVERSITY.getIntVal()){
			Universities univ = new UniversitiesDAO(ormInterface).getUnivById(dir.getOwnerId());
			UnivRoleCheck urc = new UnivRoleCheck(univ, u);
			if(urc.isAdmin()){
				exitIndex = exitOn;
			}else if(urc.isTeacher()){
				if(exitIndex < exitOn-1)
					exitIndex = exitOn-1;
			}else if(urc.isMember()){
				if(exitIndex < exitOn-2)
					exitIndex = exitOn-2;
			}
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.USER.getIntVal()){
			Users owner = new UsersDAO(ormInterface).getUserByPk(dir.getOwnerId());
			if(UserUserRelationshipCheck.isMyself(u, owner)){
				exitIndex = exitOn;
			}else if(UserUserRelationshipCheck.isSharedCourseInstance(u, owner)){
				if(exitIndex < exitOn-1)
					exitIndex = exitOn-1;
			}else if(UserUserRelationshipCheck.isSharedDepartment(u, owner)){
				if(exitIndex < exitOn-2)
					exitIndex = exitOn-2;
			}else if(UserUserRelationshipCheck.isSharedUniv(u, owner)){
				if(exitIndex < exitOn-3)
					exitIndex = exitOn-3;
			}
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.GROUP.getIntVal()){
			Groups g = new GroupsDAO(ormInterface).getGroupById(dir.getOwnerId());
			if(u.isGroupMember(g) || UnivRoleCheck.isAdmin(g.getUniversity(), u)){
				exitIndex = exitOn;
			}else if(UnivRoleCheck.isStudent(g.getUniversity(), u)){
				if(exitIndex < exitOn - 1)
					exitIndex = exitOn - 1;
			}else{
				if(exitIndex < exitOn - 2)
					exitIndex = exitOn - 2;
			}
		}
		
		for(int i=0; i<=exitIndex; i++){
			allowedPerms.add(allPerms.get(i));
		}
		
		return allowedPerms;
	}

	public static boolean isEditable(FileDirectories dir, Users user) {
		if(user==null || dir == null)
			return false;
			
		ORMInterface ormInterface = EduShareSession.get().getSessionORMInterface();
		if(dir.getOwnerType()==FileDirectories.DIRECTORY_OWNER_TYPE.COURSE_INSTANCE.getIntVal()){
			CourseInstances ci = new CourseInstancesDAO(ormInterface).getCourseInstanceById(dir.getOwnerId());
			if(ci.getStatus() == CourseInstances.COURSE_CLOSED || ci.getStatus() == CourseInstances.COURSE_CLOSED_ADMINISTRATIVE)
				return false;
			if(CourseRoleCheck.isAdmin(ci, user)||CourseRoleCheck.isTeacher(ci, user))
				return true;
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.DEPARTMENT.getIntVal()){
			Departments d = new DepartmentsDAO(ormInterface).getDepartmentByPk(dir.getOwnerId());
			if(DeptRoleCheck.isUnivAdmin(d, user)||DeptRoleCheck.isPrimaryAdmin(d, user)||DeptRoleCheck.isSecondaryAdmin(d, user))
				return true;
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.UNIVERSITY.getIntVal()){
			Universities u = new UniversitiesDAO(ormInterface).getUnivById(dir.getOwnerId());
			if(UnivRoleCheck.isAdmin(u, user))
				return true;
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.USER.getIntVal()){
			Users owner = new UsersDAO(ormInterface).getUserByPk(dir.getOwnerId());
			if(UserUserRelationshipCheck.isMyself(user, owner))
				return true;
		}else if(dir.getOwnerType() == FileDirectories.DIRECTORY_OWNER_TYPE.GROUP.getIntVal()){
			Groups g = new GroupsDAO(ormInterface).getGroupById(dir.getOwnerId());
			if(user.isGroupMember(g) || UnivRoleCheck.isAdmin(g.getUniversity(), user))
				return true;
		}
		return false;
	}
	
}
